--- 模块功能：socket客户端数据发送处理
-- @author openLuat
-- @module socketLongConnection.socketOutMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28

--协议头
local PROTOHEADER ={0xAA,0xAA,0x55 }
--协议尾
local PROTOENDER ={0xEF }
--设备编号
DEVICEID={0x88,0x88,0x88,0x01 }
DEVICESTRING="0000"
--指令编号，其中01表示心跳，03表示安全验证，10上传gps及电压，11上传重量
 PROTOORDER_HEART      = {0x01}
 PROTOORDER_SECURITY   = {0x03}
 PROTOORDER_GPS        = {0x10}
 PROTOORDER_WEIGHT     = {0x11 }
 PROTOORDER_DEVICENUM     = {0x12 }
 SECRETSALT = "hnzk"
--全局故障代码
ERR_NO = 0;--掉线
ERR_VERIFY = 1;--验证失败
ERR_FALL = 2;--掉线

ERRCODE = -1
module(...,package.seeall)
require "misc"
--数据发送的消息队列
local msgQueue = {}

--将数组组装成协议需要的数据
 function composeHeartData(order,data)
--    return (header..deviceId..order..length..data..checksum..ender);
    local s ,sum = nil,0
--头部
    for i=1,#PROTOHEADER,1 do
        s=s and s..string.char(PROTOHEADER[i])or string.char(PROTOHEADER[i])
        --        log.info("sum",sum)
    end
--设备编号
    for i=1,#DEVICEID,1 do
        s=s and s..string.char(DEVICEID[i])or string.char(DEVICEID[i])
        sum = sum+DEVICEID[i]
        --        log.info("sum",sum)
    end
--命令编号
    for i=1,#order,1 do
        s=s and s..string.char(order[i])or string.char(order[i])
        sum = sum+order[i]
        --        log.info("sum",sum)
    end
--数据长度,支持最大256字节
    s= s and s..string.char(0x00) or string.char(0x00)
    s=s and s..string.char(#data)or string.char(#data)
    sum = sum+#data;

--数据
    for i=1,#data,1 do
        local charNum = string.byte(string.sub(data,i,i));
        s=s and s..string.char(charNum)or string.charstring.byte(charNum)
        sum = sum+charNum
    end


--校验和
    local checkSum = bit.band(0xFFFF,sum);
----    取反
--    local checkResult = bit.band(0xFFFF,bit.bnot(checkSum)+1)
--    log.info("checkResult1",bit.bnot(checkSum))
--     log.info("checkResult2",bit.band(0xFFFF,bit.bnot(checkSum)+1))
    local highCheck = bit.band(0xff,bit.rshift(checkSum,8))
    log.info("highcheck",highCheck)
    local lowCheck = bit.band(0xff,checkSum);
    s = s and s..string.char(highCheck) or string.char(highCheck)
    s = s and s..string.char(lowCheck) or string.char(lowCheck)
--结尾
    for i=1,#PROTOENDER,1 do
        s=s and s..string.char(PROTOENDER[i])or string.char(PROTOENDER[i])
    end
    log.info("sum",sum)
    log.info("SSSSSS",string.toHex(s," "))
    return s

end

function insertMsg(data,user)
    table.insert(msgQueue,{data=data,user=user})
end

local function sndHeartCb(result)
    log.info("socketOutMsg.sndHeartCb",result)
    if result then sys.timerStart(sndHeart,60000) end
end
local function verifyCb(result)
    sys.taskInit(function()
        log.info("socketOutMsg.verifyCb",result)
        if result then
                ret, data = sys.waitUntil("VERIFYSUCCESS", 5000)
            if(ret)then
            --            验证通过，发送心跳包
                sndHeart()
--                sndWeight()
                _G.ERRCODE = ERR_NO
            else
            --            验证失败，主动断开连接
                _G.ERRCODE =ERR_VERIFY
            end
        end
    end)

end
function sndWeightCb()
    sys.timerStart(sndWeight,5000)
end
function sndHeart()

    insertMsg(composeHeartData(PROTOORDER_HEART,"0"),{cb=sndHeartCb})
end
function sndWeight()
    log.info("sendWeight-------------------------------")
    insertMsg(composeHeartData(PROTOORDER_WEIGHT,"201901221025000050.5020190122102625"),{cb=sndWeightCb})
end


--- 初始化“socket客户端数据发送”
-- @return 无
-- @usage socketOutMsg.init()
function init()
--    sndHeart()
--    首先进行安全验证，验证通过后进行心跳包发送，安全验证失败
    vetification();
end

--- 去初始化“socket客户端数据发送”
-- @return 无
-- @usage socketOutMsg.unInit()
function unInit()
    sys.timerStop(sndHeart)
    sys.timerStop(sndLoc)
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
        if outMsg.user and outMsg.user.cb then outMsg.user.cb(false,outMsg.user.para) end
    end
end

--- socket客户端是否有数据等待发送
-- @return 有数据等待发送返回true，否则返回false
-- @usage socketOutMsg.waitForSend()
function waitForSend()
    return #msgQueue > 0
end

--安全验证
function vetification()
--    获取时间戳
    local tm = misc.getClock()
    local timeStamp =string.format("%04d%02d%02d%02d%02d%02d", tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec)
    log.info("testNtp.printTime",timeStamp );
    local string_verify = timeStamp..SECRETSALT;
    local string_md5 = crypto.md5(string_verify,#(string_verify))
    log.info("md5",string_md5)
    insertMsg(composeHeartData(PROTOORDER_SECURITY,timeStamp..string_md5),{cb=verifyCb})
end
--- socket客户端数据发送处理
-- @param socketClient，socket客户端对象
-- @return 处理成功返回true，处理出错返回false
-- @usage socketOutMsg.proc(socketClient)
function proc(socketClient)
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
        local result = socketClient:send(outMsg.data)
        if outMsg.user and outMsg.user.cb then outMsg.user.cb(result,outMsg.user.para) end
        if not result then return end
    end
    return true
end
--ok()
